package com.huarui.initial.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.ewaf.framework.service.BaseService;
import org.ewaf.framework.util.BeanUtil;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;

import com.huarui.code.dao.ICodeGenericDao;
import com.huarui.initial.dao.IInitialDao;
import com.huarui.initial.model.Initial;
import com.huarui.initial.util.InitialErrorsEnum;
import com.huarui.initial.util.InitialUtil;
import com.huarui.initialItem.dao.IinitialItemDao;
import com.huarui.initialItem.model.InitialItem;
import com.huarui.inventory.dao.IInventoryDao;
import com.huarui.inventory.model.Inventory;
import com.huarui.part.dao.IPartDao;
import com.huarui.part.dao.IPartPropertyDao;
import com.huarui.part.model.Part;
import com.huarui.part.model.PartProperty;
import com.huarui.quotation.dao.IQuotationDao;
import com.huarui.quotation.model.Quotation;
import com.huarui.quotation.service.QuotationSearchService;
import com.huarui.quotation.service.QuotationService;
import com.huarui.user.model.SessionMessage;

public class InitialSubmitService extends BaseService{
	
	private static final long serialVersionUID = 1L;
	private final static Logger logger = Logger.getLogger(InitialSubmitService.class);
	private IinitialItemDao iInitialItemDao;
	private ICodeGenericDao iCodeGenericDao;
	private IPartPropertyDao iPartPropertyDao;
	private IPartDao iPartDao;
	private IInventoryDao iInventoryDao;
	private IQuotationDao iQuotationDao;
	private InitialService initialService;
	private QuotationService quotationService;

	private IInitialDao getDao() {
		return (IInitialDao) dao;
	}
	
	/* 提交期初单 */
	@SuppressWarnings("unchecked")
	public Map<String,Object> sumbit(final Integer id, final SessionMessage sm,final Initial initialtemp) {
		Map<String,Object> resultMap=(Map<String, Object>) transactionTemplate.execute(new TransactionCallback() {
			Map<String,Object> resultMap=new HashMap<String, Object>();
			@Override
			public Object doInTransaction(TransactionStatus status) {
				try{
					Initial correctInitial = selectInitialCondtion(id, sm,true);
					if(correctInitial==null){
						resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.ERROR_MSG_RECORD_DELETE.getMsg());
						status.setRollbackOnly();
						return resultMap;
					}else if(sm.getUserId().intValue()!=correctInitial.getCurrentorId()){
						resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.ERROR_MSG_RECORD_RECEIVE.getMsg());
						status.setRollbackOnly();
						return resultMap;
					}
					correctInitial.setGmtAccept(initialtemp.getGmtAccept());
					correctInitial.setMemo(initialtemp.getMemo());
					// 正确数据期初单的提交
					List<InitialItem> correctlist=handleInitial(sm, correctInitial,resultMap);
					/*int subSize=500;
					for(int i=0;i<=correctlist.size()/subSize;i++){
						List<InitialItem> subCorrectlist=correctlist.subList(i*subSize, (i+1)*subSize<correctlist.size()?(i+1)*subSize:correctlist.size());
						影响partproperty表的操作
						handlePartProperty(sm,subCorrectlist);
						//操作库存表
						List<Inventory> inventoryList=handleInventory(sm,correctInitial,subCorrectlist);
						//影响quotation
						handleQuotation(inventoryList,subCorrectlist,sm,resultMap);

					}*/
					List<PartProperty> partProperty=handlePartProperty(sm,correctlist);
					quotationService.batchOperationQuotation(partProperty);
					//操作库存表
					handleInventory(sm,correctInitial,correctlist);
					Map<String,Object> inVo=initialService.getInitialVOById(id,sm);
					resultMap.put("initial",inVo.get("data"));
				}catch(Exception e){
					logger.error("提交期初单错误"+e.toString() ,e);
					resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.ERROR_MSG_DATABASE.getMsg());
					status.setRollbackOnly();
					return resultMap;
				}
				resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(), InitialErrorsEnum.RESULT_TYPE_SUCCESS.getMsg());
				return resultMap;
			}
		});
		return resultMap;
	}
	private Initial selectInitialCondtion(final Integer id,
			final SessionMessage sm,boolean isLock) {
		Map<String,Object> map=new HashMap<String, Object>();
		map.put("id", id);
		map.put("companyId", sm.getCompanyId());
		//map.put("status", 0);
		if(isLock==true)map.put("isLock", isLock);
		Initial	correctInitial = (Initial) getDao().getById(map);
		return correctInitial;
	}


	/**
	 * 影响initial及initialItem表操作
	 * @param sm
	 * @param correctInitial
	 * @return
	 */
	private List<InitialItem> handleInitial(final SessionMessage sm,
			Initial correctInitial,Map<String,Object> resultMap) {
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("initialId", correctInitial.getId());
		map.put("errorType", getErrorTypeList(0, 2));// 0正确,2警告
		List<InitialItem> correctlist = iInitialItemDao
				.findAllItemsByCondition(map);
		BigDecimal correctAmount = BigDecimal.ZERO;
		for (InitialItem item : correctlist) {
			correctAmount = correctAmount.add(InitialUtil.calAmout(item));
		}
		correctInitial.setAmount(correctAmount);
		correctInitial.setStatus(1);// 正式提交
		correctInitial.setGmtSubmit(new Date());
		correctInitial.setSubmitter(sm.getUserId());
		dao.update(correctInitial);

		// 错误数据期初单的提交
		Map<String,Object> errorMap = new HashMap<String,Object>();
		errorMap.put("initialId", correctInitial.getId());
		errorMap.put("errorType", getErrorTypeList(1));// 1错误
		List<InitialItem> errorlist = iInitialItemDao
				.findAllItemsByCondition(errorMap);
		if (errorlist.size() > 0) {
			Initial errorInitial = createInitial(sm);
			BigDecimal errorAmount =BigDecimal.ZERO;
			for (InitialItem item : errorlist) {
				errorAmount = errorAmount.add(InitialUtil.calAmout(item));
				item.setInitialId(errorInitial.getId());
			}
			iInitialItemDao.batchUpdate(errorlist);
			errorInitial.setAmount(errorAmount);
			errorInitial.setStatus(0);// 草稿
			dao.update(errorInitial);
			resultMap.put("errorInitial",errorInitial);
		}
		return correctlist;
	}
	

	/**
	 * 影响partproperty表的操作
	 * @param sm
	 * @param map
	 * @param correctlist 
	 * @return
	 */
	private List<PartProperty> handlePartProperty(SessionMessage sm,List<InitialItem> correctlist) {
		List<PartProperty> list = null;
		Map<String,Object> maptemp = new HashMap<String,Object>();
		maptemp.put("companyId", sm.getCompanyId());
		maptemp.put("initialItemList", correctlist);
		maptemp.put("isLock", true);
		list = iPartPropertyDao.getPartAndPartPropertyByCondition(maptemp);//获取excel表此公司的零件。
		Map<Integer, PartProperty> partProMap = new HashMap<Integer, PartProperty>(); //将此公司所有的零件放入corMap中
		for(PartProperty partProperty:list){
			partProMap.put(partProperty.getPartId(), partProperty);
		}
		maptemp.clear();
		maptemp.put("initialItemList", correctlist);
		List<Part> partList=iPartDao.getPartListByConditions(maptemp);
		Map<Integer,Part> partMap=new HashMap<Integer,Part>();
		for(Part part:partList){
			partMap.put(part.getId(), part);
		}
		Map<String,PartProperty> isdouble=new HashMap<String,PartProperty>();
		List<PartProperty> ParProList = new ArrayList<PartProperty>();  // 在partproperty表里还不存在的零件list
		for (InitialItem item : correctlist) {
			PartProperty partProperty = (PartProperty) partProMap.get(item.getPartId());
			if (partProperty== null) {
				Part part=(Part) partMap.get(item.getPartId());
				partProperty=new PartProperty();
				BeanUtil.copyProperties(partProperty, part);
				if(isdouble.get(partProperty.getSource().toString()+part.getCode())==null){
					isdouble.put(part.getSource().toString()+part.getCode(), partProperty);
				}else{
					calpartproperty(item, isdouble.get(partProperty.getSource().toString()+part.getCode()));
					continue;
				}	
				partProperty.setId(null);
				partProperty.setCompanyId(sm.getCompanyId());
				partProperty.setPartId(part.getId());
				partProperty.setCost(item.getCost());
				partProperty.setMinPrice(item.getCost());
				partProperty.setInsurancePrice(item.getInsurancePrice());
				partProperty.setMaxOnHand(item.getMaxOnHand());
				partProperty.setMinOnHand(item.getMinOnHand());
				partProperty.setOnHand(item.getQuantity());
				partProperty.setCarModel(item.getCarModel());
				partProperty.setSwapCode(item.getSwapCode());
				partProperty.setRetailPrice(item.getRetailPrice());
				partProperty.setBrand(item.getBrand());
				partProperty.setOrigin(item.getOrigin());
				partProperty.setGmtCreate(new Date());
				partProperty.setGmtModify(new Date());
			} else {
				calpartproperty(item, partProperty);
				partProperty.setGmtModify(new Date());
				
			}
			ParProList.add(partProperty);
		}
		//iPartPropertyDao.batchInsertPartProperty(nEixtParProList);
		//iPartPropertyDao.batchUpdatePartProperty(exitParProList);
		return ParProList;
	}

	private void calpartproperty(InitialItem item, PartProperty partProperty) {
		partProperty.setMinOnHand((partProperty.getMinOnHand()==null?0:partProperty.getMinOnHand())+(item.getMinOnHand()==null?0:item.getMinOnHand())); // 下限库存数
		partProperty.setMaxOnHand((partProperty.getMaxOnHand()==null?0:partProperty.getMaxOnHand())+(item.getMaxOnHand()==null?0:item.getMaxOnHand())); // 上限库存数
		BigDecimal cost = calCost(item, partProperty); // 平均成本
		partProperty.setCost(cost);
		if (item.getMinPrice() != null&& partProperty.getMinPrice() != null)     //最小价格
			partProperty.setMinPrice(new BigDecimal(Math.min(
					item.getMinPrice().doubleValue(),
					partProperty.getMinPrice().doubleValue())));
	}
	
	/*影响库存表操作*/
	private List<Inventory> handleInventory(final SessionMessage sm,
			Initial correctInitial, List<InitialItem> correctlist) {
		List<Inventory> inventoryList=new ArrayList<Inventory>();
		for(InitialItem item:correctlist){
			Inventory inventory=new Inventory();
			inventory.setCompanyId(sm.getCompanyId());
			inventory.setStoreId(item.getStoreId());
			inventory.setShelf(item.getShelf());
			inventory.setPartId(item.getPartId());
			inventory.setCode(item.getCode());
			inventory.setSource(item.getSource());
			inventory.setName(item.getName());
			inventory.setNameEn(item.getNameEn());
			inventory.setMeasurementUnit(item.getMeasurementUnit());
			inventory.setPartCategoryId(item.getPartCategoryId());
			inventory.setLevel1Id(item.getLevel1Id());
			inventory.setLevel1Name(item.getLevel1Name());
			inventory.setLevel2Name(item.getLevel2Name());
			
			inventory.setBrand(item.getBrand());
			inventory.setOrigin(item.getOrigin());
			inventory.setCost(item.getCost());
			inventory.setRetailPrice(item.getRetailPrice());
			inventory.setInsurancePrice(item.getInsurancePrice());
			inventory.setMinPrice(item.getMinPrice());
			inventory.setInitQuantity(item.getQuantity());
			inventory.setOnHand(item.getQuantity());
			inventory.setPublicanLevel(Inventory.publicanLevel_PARTNER);
			inventory.setDocumentType(Inventory.DDOCUMENT_TYPE_INITIAL);
			inventory.setDocumentId(correctInitial.getId());
			inventory.setDocumentCode(correctInitial.getCode());
			inventory.setPartId(item.getPartId());
			
			//最新增加

			inventory.setCarModel(item.getCarModel());
			//inventory.setDurability(part)
			//iInventoryDao.create(inventory);
			inventoryList.add(inventory);
			
			
			
			
		}
		iInventoryDao.batchInsertInventory(inventoryList);
		return inventoryList;
	}
	

	private void handleQuotation(List<Inventory> inventoryList,List<InitialItem> initialItemList,SessionMessage sm,Map<String,Object> resultMap){
		Map<Integer,InitialItem> itemMap=new HashMap<Integer,InitialItem>();
		for(InitialItem initialItem:initialItemList){
			itemMap.put(initialItem.getPartId(), initialItem);
		}
		

		List<Quotation> quoList=new ArrayList<Quotation>();
		for(Inventory inventory:inventoryList){
			InitialItem initialItem=itemMap.get(inventory.getPartId());
			Quotation quotation=new Quotation();
			quotation.setId(inventory.getId());
			quotation.setPartId(initialItem.getPartId());
			quotation.setCode(initialItem.getCode());
			quotation.setSource(initialItem.getSource());
			quotation.setName(initialItem.getName());
			quotation.setNameEn(initialItem.getNameEn());
			quotation.setPyCode(initialItem.getPyCode());
			quotation.setMeasurementUnit(initialItem.getMeasurementUnit());
			quotation.setSwapCode(initialItem.getSwapCode());
			quotation.setPartCategoryId(initialItem.getPartCategoryId());
			quotation.setLevel1Name(initialItem.getLevel1Name());
			quotation.setLevel2Name(initialItem.getLevel2Name());
			quotation.setLevel1Id(initialItem.getLevel1Id());
			quotation.setBrand(initialItem.getBrand());
			quotation.setOrigin(initialItem.getOrigin());
			quotation.setOnHand(inventory.getOnHand());
			quotation.setRetailPrice(initialItem.getRetailPrice());
			quotation.setPublicanLevel(inventory.getPublicanLevel());
			quotation.setGmtCreate(new Date());
			quotation.setGmtModify(new Date());
			quotation.setTmsVersion(new Date());
			quoList.add(quotation);
		}
		@SuppressWarnings("unused")
		boolean hasPermission=iQuotationDao.batchInsertQuotation(quoList,sm.getCompanyId());
		/*if(!hasPermission){
			resultMap.put(InitialErrorsEnum.SUCCESS.getMsg(),"");
		}*/
	}
	private List<Integer> getErrorTypeList(Object... T) {
		List<Integer> errorTypeList = new ArrayList<Integer>();
		for (int i = 0; i < T.length; i++) {
			errorTypeList.add((Integer) T[i]);
		}
		return errorTypeList;
	}
	public Initial createInitial(SessionMessage sm) {
		Initial initial = new Initial();
		return createInitial(sm,initial);
	}
	public Initial createInitial(SessionMessage sm,Initial initial) {
		initial.setAmount(new BigDecimal(0));
		initial.setCompanyId(sm.getCompanyId());
		initial.setCreatorId(sm.getUserId());
		initial.setCode(iCodeGenericDao.getNewCode(sm.getCompanyId(), "initial"));
		initial.setGmtCreate(new Date());
		initial.setStatus(0);
		initial.setCurrentorId(sm.getUserId());
		this.getDao().create(initial);
		return initial;
	}
	private BigDecimal calCost(InitialItem item, PartProperty partProperty) {
		if(item.getCost().equals(BigDecimal.ZERO)||item.getQuantity()==0){
			return partProperty.getCost();
		}else{
			return item.getCost().multiply(BigDecimal.valueOf(item.getQuantity())).add(partProperty.getCost().multiply(BigDecimal.valueOf(partProperty.getOnHand())))
			.divide(BigDecimal.valueOf(item.getQuantity()+partProperty.getOnHand()),4);
		}
	}

	public void setiInitialItemDao(IinitialItemDao iInitialItemDao) {
		this.iInitialItemDao = iInitialItemDao;
	}

	public void setiCodeGenericDao(ICodeGenericDao iCodeGenericDao) {
		this.iCodeGenericDao = iCodeGenericDao;
	}

	public void setiPartPropertyDao(IPartPropertyDao iPartPropertyDao) {
		this.iPartPropertyDao = iPartPropertyDao;
	}

	public void setiPartDao(IPartDao iPartDao) {
		this.iPartDao = iPartDao;
	}

	public void setiInventoryDao(IInventoryDao iInventoryDao) {
		this.iInventoryDao = iInventoryDao;
	}

	public void setiQuotationDao(IQuotationDao iQuotationDao) {
		this.iQuotationDao = iQuotationDao;
	}

	public void setInitialService(InitialService initialService) {
		this.initialService = initialService;
	}

	public void setQuotationService(QuotationService quotationService) {
		this.quotationService = quotationService;
	}

	

	
}
